package com.mspbots.cw.trigger;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mspbots.api.client.CoreClient;
import com.mspbots.cw.amqp.model.Ticket;
import com.mspbots.cw.amqp.model.TicketClose;
import com.mspbots.cw.amqp.model.TriggerEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitMessagingTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.data.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.mspbots.common.TriggerEvent.CW_TICKET_CLOSE;
import static com.mspbots.common.TriggerEvent.CW_TICKET_NEW;

/**
 * @author Harry hou
 * @date 2019/11/22 15:17
 */

@Slf4j
@Component
@RequiredArgsConstructor
public class TicketTriggerEvent {

    private final RabbitMessagingTemplate messagingTemplate;
    private final ObjectMapper objectMapper;
    private final CoreClient coreClient;
    private final DatabaseClient databaseClient;


    @RabbitListener(queues = "ticket.forward")
    public void publishTicketTriggerEvent(Ticket ticket) {
        if (ticket.getCreatedTime() != null && LocalDateTime.now().minusHours(24).isBefore(ticket.getCreatedTime())) {
            if (!StringUtils.isEmpty(ticket.getAction())) {
                Map<String, Object> userMappingParam = Map.of(
                        "tenantId", ticket.getTenantId(),
                        "identifier", ticket.getExtend().get("_info").get("updatedBy").asText()
                );
                JsonNode userMapping = coreClient.get("/user-mapping/detail", userMappingParam).block();
                if (!ObjectUtils.isEmpty(userMapping)) {
                    if (!ObjectUtils.isEmpty(userMapping)) {
                        log.debug("time entry trigger {} ", ticket.getExtend().get("id").asText());
                        JsonNode extend = ticket.getExtend();
                        ObjectNode payload = (ObjectNode) extend;
                        payload.put("action", ticket.getAction().name());
                        TriggerEvent triggerEvent = new TriggerEvent();
                        triggerEvent.setTenantId(userMapping.get("tenantId").asLong());
                        triggerEvent.setEventName(CW_TICKET_NEW.getEvent());
                        triggerEvent.setScope(CW_TICKET_NEW.getScope());
                        triggerEvent.setPayload(payload);
                        triggerEvent.setUserInfo(userMapping);
                        if (ticket.getStatus().toLowerCase().contains("closed")) {
                            TriggerEvent newTriggerEvent = new TriggerEvent();
                            BeanUtils.copyProperties(triggerEvent, newTriggerEvent);
                            newTriggerEvent = publishTicketCloseTriggerEvent(newTriggerEvent, ticket);
                            this.messagingTemplate.convertAndSend("msp.trigger.event", "", newTriggerEvent);
                        }
                        this.messagingTemplate.convertAndSend("msp.trigger.event", "", triggerEvent);
                        log.debug("cw msp.trigger.event NewTicket [{}] ", this.objectMapper.convertValue(triggerEvent, JsonNode.class));
                    } else {
                        log.error("cw user [{}] has no mapping [{}]", ticket.getExtend().get("_info").get("updatedBy"), ticket.getCwId());
                    }
                }
            }
        }
    }


    private TriggerEvent publishTicketCloseTriggerEvent(TriggerEvent triggerEvent, Ticket ticket) {
        TicketClose close = new TicketClose();

        close.setCwId(ticket.getCwId());
        close.setTenantId(ticket.getTenantId());
        close.setStatusId(ticket.getStatusId());
        close.setStatus(ticket.getStatus());
        close.setUpdatedTime(ticket.getUpdatedTime());
        close.setCreatedTime(LocalDateTime.now());
        if (ObjectUtils.isEmpty(ticket.getConfigurations())
                || ticket.getConfigurations() == null
                || "null".equals(ticket.getConfigurations().asText())) {
            close.setIsConfigurations(false);
        } else {
            close.setIsConfigurations(true);
        }
        close.setConfigurations(ticket.getConfigurations());
        JsonNode extend = ticket.getExtend();
        if (extend.has("type")) {
            close.setIsType(true);
            close.setType(extend.get("type").get("name").asText());
        } else {
            close.setIsType(false);
        }

        if (extend.has("subType")) {
            close.setIsSubType(true);
            close.setSubType(extend.get("subType").get("name").asText());
        } else {
            close.setIsSubType(false);
        }

        this.databaseClient.insert().into(TicketClose.class).using(close)
                .fetch().rowsUpdated().block();

        JsonNode closeNode = this.objectMapper.convertValue(close, JsonNode.class);

        triggerEvent.setEventName(CW_TICKET_CLOSE.getEvent());
        triggerEvent.setScope(CW_TICKET_CLOSE.getScope());
        triggerEvent.setPayload(closeNode);

        log.debug("ticket repeat:{}", ticket);

        return triggerEvent;
    }


    /**
     * test for dev
     */
//    @Scheduled(cron = "0/30 * * * * ?")
    public void test() {
        Map<String, Object> params = new HashMap<>();
        params.put("tenantId", 1);
        params.put("cwId", 264501);


        JsonNode result = coreClient.get("/tickets/list", params).block();
        List<Ticket> ticket = objectMapper.convertValue(result, new TypeReference<List<Ticket>>() {
        });
        publishTicketTriggerEvent(ticket.get(0));
    }


}
